home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 2
/
Nebula Two.iso
/
SourceCode
/
Palettes
/
HotShape
/
HotShape.m
< prev
next >
Wrap
Text File
|
1995-06-12
|
5KB
|
209 lines
// HotShape.m
// By Charles G. Fleming, Educational Computing Services, Allegheny College.
// Copyright 1992 Allegheny College
// You may freely copy, distribute and reuse this code.
// Allegheny College and the author disclaim any warranty of any kind,
// expressed or implied, as to its fitness for any particular use.
// This work was partially supported by a grant from the Vira Heinz Endowment.
#import "HotShape.h"
#import "HotPath.h"
#import "SmallCell.h"
@implementation HotShape
- (const char *)getInspectorClassName
{
return "HotShapeInspector";
}
// Scale the HotShape object so that it has unit length and height.
// Give it a custom cell so that it can be resized to an arbitrarily small
// size in InterfaceBuilder. The default shape will be a diamond shape.
- initFrame:(const NXRect *)frameRect
{
SmallCell *smallCell;
self = [super initFrame:frameRect];
hotPathName = malloc(1);
visible = YES;
[self scale:bounds.size.width :bounds.size.height];
smallCell = [[SmallCell allocFromZone:[self zone]] init];
[self setCell:smallCell];
// Define the hot shape paths that will be used.
setHotPaths();
tag = 0;
[self setHotPathName:"diamond"];
[self setOpaque:NO];
return self;
}
- (BOOL)acceptsFirstMouse
{
return YES;
}
- drawSelf:(const NXRect *)rects :(int)rectCount
{
drawHotPath(hotPathName, visible);
return self;
}
- awake
{
setHotPaths();
return self;
}
- sizeTo:(NXCoord)width :(NXCoord)height
{
[super sizeTo:width :height];
[self scale:bounds.size.width :bounds.size.height];
return self;
}
- setHotPathName:(const char *)name
{
free(hotPathName);
hotPathName = malloc(strlen(name) + 1);
strcpy(hotPathName, name);
return self;
}
- (char *)hotPathName
{
return hotPathName;
}
- (BOOL)visible
{
return visible;
}
- setVisible:(BOOL)seeIt
{
visible = seeIt;
return self;
}
- read:(NXTypedStream *)typedStream
{
[super read:typedStream];
NXReadTypes(typedStream, "*s", &hotPathName, &visible);
return self;
}
- write:(NXTypedStream *)typedStream
{
[super write:typedStream];
NXWriteTypes(typedStream, "*s", &hotPathName, &visible);
return self;
}
- mouseDown:(NXEvent *)theEvent
{
SEL action;
NXEvent *nextEvent;
BOOL finished = NO, done = NO;
int at;
NXPoint windowCoords = {theEvent->location.x, theEvent->location.y};
View *currentview, *currentSuperview;
List *subviewList;
if([self inHotPath:windowCoords])
{
if([cell isEnabled])
while(!finished)
{
nextEvent = [NXApp getNextEvent:NX_MOUSEUPMASK];
if(nextEvent->type == NX_MOUSEUP)
{
windowCoords.x = nextEvent->location.x;
windowCoords.y = nextEvent->location.y;
if([self inHotPath:windowCoords])
{
action = [cell action];
if(action)
[self sendAction:action to:[cell target]];
}
finished = YES;
}
}
}
else
{
// Pass on to the location to lower hotshape;
currentview = self;
currentSuperview = superview;
while(currentSuperview && !done)
{
subviewList = [currentSuperview subviews];
at = [subviewList indexOf:currentview] - 1;
done = [self traverseTreeWithRoot:currentSuperview startAt:at
usingLocation:windowCoords];
currentview = currentSuperview;
currentSuperview = [currentSuperview superview];
}
}
return self;
}
// Traverse a view's subview hierarchy, starting at the specified node,
// until we get to the front-most hotshape. If specified location is in
// the hot path of the front-most hotshape we return YES. In all other
// cases we return NO.
- (BOOL)traverseTreeWithRoot:root startAt:(int)at
usingLocation:(NXPoint)windowCoords
{
SEL action;
BOOL flag = NO;
List *subviewList;
int index;
id node;
SmallCell *smallCell;
subviewList = [root subviews];
for(index = at; index > -1 && !flag; index--)
{
node = [subviewList objectAt:index];
if([node subviews])
flag = [self traverseTreeWithRoot:node
startAt:[[node subviews] count]-1
usingLocation:windowCoords];
else
if([node isKindOf:[HotShape class]])
{
flag = [node inHotPath:windowCoords];
if(flag)
{
smallCell = [node cell];
action = [smallCell action];
if(action)
[node sendAction:action to:[smallCell target]];
}
}
}
return flag;
}
// Determines if a point (given in window coords) is in the hot path.
- (BOOL)inHotPath:(NXPoint)location
{
NXPoint viewCoords = {location.x, location.y};
int inRegion = NO;
[self convertPoint:&viewCoords fromView:nil];
[self lockFocus];
inHotRegion(hotPathName, viewCoords.x, viewCoords.y, &inRegion);
[self unlockFocus];
return inRegion;
}
@end